library(plyr)

# create unique identifer for each horse
runners <- transform(runners, name.sire_name = paste(name, sire_name, sep ="."))

# calculate input for recency weights
runners <- runners[with(runners, order(name.sire_name, meeting_date)), ]
day <- split(runners$meeting_date, runners$name.sire_name)
day <- sapply(day, FUN = function(y) as.matrix(y - y[1]))
day <- do.call(rbind, day)
runners <- transform(runners, day = day)
rm(day)

# Recode NAs for finish_position & distance_behind_yards
runners$distance_behind_winner[runners$finish_position == 1] <- 0
stats <- aggregate(cbind(finish_position, distance_behind_winner) ~
  meeting_date + course + distance_yards, runners, FUN = max, na.rm = T)
runners <- merge(runners, stats,
                 by = c("meeting_date", "course", "distance_yards"),
                 suffixes = c("", ".max"))
runners$finish_position[is.na(runners$finish_position)] <-
  runners$finish_position.max[is.na(runners$finish_position)]
runners$distance_behind_winner[is.na(runners$distance_behind_winner)] <-
  runners$distance_behind_winner.max[is.na(runners$distance_behind_winner)]
runners <- subset(runners, T,
                  -c(finish_position.max, distance_behind_winner.max))

# Recode NAs for speed_rating
stats <- aggregate(speed_rating ~
  meeting_date + course + distance_yards, runners, FUN = min, na.rm = T)
runners <- merge(runners, stats,
                 by = c("meeting_date", "course", "distance_yards"),
                 suffixes = c("", ".min"))
runners$speed_rating[is.na(runners$speed_rating)] <-
  runners$speed_rating.min[is.na(runners$speed_rating)]
runners <- subset(runners, T,
                  -c(speed_rating.min))

# calculate moving recency-weighted statistics
runners <- runners[with(runners, order(name.sire_name, meeting_date)), ]
stats <- dlply(runners, .(name.sire_name), .fun =
  function(DF) rollmean(DF$day, DF[, c("finish_position",
                                       "distance_behind_winner",
                                       "speed_rating")
                                   ]
  )
)
stats <- do.call(rbind, stats)
runners <- cbind(runners, stats)
rm(stats)